package com.xf.system.utils.redis;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @author xiefengf
 */
@Component
public class RedisUtils {

    public final static String symbol = "-----";

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * -----------------------------------------以下的String类型操作---------------------------------------------------------------
     */

    /**
     * 获取Redis中所有key
     * @return 所有的key
     */
    public Set<String> getAllKeys() {
        Set<String> keys = new HashSet<>();
        // 使用scan命令获取所有的key
        redisTemplate.execute((RedisCallback<Void>) connection -> {
            ScanOptions options = ScanOptions.scanOptions().match("*").count(1000).build();
            try (Cursor<byte[]> cursor = connection.scan(options)) {
                while (cursor.hasNext()) {
                    keys.add(new String(cursor.next()));
                }
            }
            return null;
        });
        return keys;
    }

    /**
     * 设置String类型缓存
     *
     * @param key   键
     * @param value 值
     */
    public void setString(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 设置缓存并设置过期时间
     *
     * @param key    键
     * @param value  值
     * @param expire 过期时间（单位：秒）
     * @return 是否设置成功
     */
    public void setString(String key, Object value, long expire) {
        redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
    }

    /**
     * 获取String类型缓存值
     *
     * @param key 键
     * @return 值
     */
    public Object getString(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 删除缓存
     *
     * @param key 键
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }


    /**
     * 判断缓存是否存在
     *
     * @param key 键
     * @return 是否存在
     */
    public boolean hasKey(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.hasKey(key));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 自增操作
     * 键为key的字符串类型的值自增1，并返回自增后的新值。如果键不存在，则会先创建一个值为0的新键再执行自增操作。这个方法通常用于计数器场景。
     *
     * @param key   键
     * @param delta 增量
     * @return 自增后的值
     */
    public Long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 设置缓存的过期时间
     *
     * @param key    键
     * @param expire 过期时间（单位：秒）
     * @return 是否设置成功
     */
    public void expire(String key, long expire) {
        redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    /**
     * 获取缓存的过期时间
     * @param key 键
     * @return 过期时间（单位：秒），返回-1代表永不过期
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * -----------------------------------------以下的Set类型操作---------------------------------------------------------------
     */

    /**
     * 向set中添加一个或多个成员
     */
    public Long add(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    /**
     * 返回集合中的所有成员
     */
    public Set<Object> members(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 移除集合中一个或多个成员
     */
    public Long remove(String key, Object... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 返回集合中元素的数量
     */
    public Long size(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 判断 member 元素是否是集合 key 的成员
     */
    public Boolean isMember(String key, String member) {
        return redisTemplate.opsForSet().isMember(key, member);
    }








    /**
     * 清空redis所有key
     */
    public void flushDb() {
        Set<String> keys = redisTemplate.keys("*");
        if (keys != null && keys.size() != 0){
            redisTemplate.delete(Objects.requireNonNull(redisTemplate.keys("*")));
        }
    }

}
